package io.renren.modules.customer.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import io.renren.common.CommonConstants;
import io.renren.common.enums.CommonProcessStatus;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.Query;
import io.renren.modules.customer.dao.MessageRequestDao;
import io.renren.modules.customer.entity.CustomerEntity;
import io.renren.modules.customer.entity.MessageRequestEntity;
import io.renren.modules.customer.service.CustomerService;
import io.renren.modules.customer.service.MessageRequestService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.StringWriter;
import java.util.*;
import java.util.stream.Collectors;


@Service("messageRequestService")
public class MessageRequestServiceImpl extends ServiceImpl<MessageRequestDao, MessageRequestEntity> implements MessageRequestService, InitializingBean {

    private static final Logger LOGGER = LoggerFactory.getLogger(MessageRequestServiceImpl.class);

    @Autowired
    private CustomerService customerService;

    private Configuration freemarkerConfiguration = null;

    @Override
    public void afterPropertiesSet() throws Exception {
        this.freemarkerConfiguration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        // 配置freemarker
        freemarkerConfiguration.setNumberFormat("0.##");
        freemarkerConfiguration.setClassicCompatible(true);
    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        LambdaQueryWrapper<MessageRequestEntity> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank((String) params.get("mobilePhone"))) {
            queryWrapper.eq(MessageRequestEntity::getMobilePhone, ((String) params.get("mobilePhone")).trim());
        }
        if (StringUtils.isNotBlank((String) params.get("batchNumber"))) {
            queryWrapper.eq(MessageRequestEntity::getBatchNumber, ((String) params.get("batchNumber")).trim());
        }
        if (StringUtils.isNotBlank((String) params.get("serialNumber"))) {
            queryWrapper.eq(MessageRequestEntity::getSerialNumber, ((String) params.get("serialNumber")).trim());
        }
        if (StringUtils.isNotBlank((String) params.get("messageId"))) {
            queryWrapper.eq(MessageRequestEntity::getMessageId, ((String) params.get("messageId")).trim());
        }
        IPage<MessageRequestEntity> page = this.page(
                new Query<MessageRequestEntity>().getPage(params),
                queryWrapper
        );
        return new PageUtils(page);
    }

    @Override
    public List<String> getPhoneNumbersWithPendingRequests(List<String> phones) {
        if (phones == null || phones.size() < 1) {
            return Collections.emptyList();
        } else {
            LambdaQueryWrapper<MessageRequestEntity> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(MessageRequestEntity::getRequestStatus, CommonProcessStatus.PENDING);
            queryWrapper.in(MessageRequestEntity::getMobilePhone, phones);
            List<MessageRequestEntity> entities = this.baseMapper.selectList(queryWrapper);
            if (entities == null) {
                return Collections.emptyList();
            } else {
                return entities.stream().map(MessageRequestEntity::getMobilePhone).collect(Collectors.toList());
            }
        }
    }

    @Override
    public void batchSendMessages(String batchNumber, Long[] ids, Long currentUserId, String template) {
        if (ids != null && ids.length > 0 && StringUtils.isNotBlank(template)) {
            //找到用户
            List<CustomerEntity> customerEntities = this.customerService.getCustomersByIds(ids);
            //对于有正在执行任务中的用户，不需要重复发送
            List<String> pendingTaskPhoneNumbers = this.getPhoneNumbersWithPendingRequests(customerEntities.stream().map(CustomerEntity::getMobilePhone).collect(Collectors.toList()));
            //入库
            Date now = new Date();
            Map<String, String> params = null;
            StringTemplateLoader stringLoader = new StringTemplateLoader();
            Template freemarkerTemplate = null;
            int i = 1;
            for (CustomerEntity customerEntity : customerEntities) {
                if (!pendingTaskPhoneNumbers.contains(customerEntity.getMobilePhone())) {
                    MessageRequestEntity entity = new MessageRequestEntity();
                    entity.setCreateUserId(currentUserId);
                    entity.setCreateTime(now);
                    entity.setBatchNumber(batchNumber);
                    entity.setMobilePhone(customerEntity.getMobilePhone());
                    entity.setRequestCount(0);
                    entity.setRequestStatus(CommonProcessStatus.PENDING);
                    params = new HashMap<>();
                    params.put(CommonConstants.PARAM_MOBILE, customerEntity.getMobilePhone());
                    params.put(CommonConstants.PARAM_USERNAME, customerEntity.getName());
                    stringLoader.putTemplate(customerEntity.getMobilePhone(), template);
                    this.freemarkerConfiguration.setTemplateLoader(stringLoader);
                    try {
                        freemarkerTemplate = this.freemarkerConfiguration.getTemplate(customerEntity.getMobilePhone());
                        StringWriter sw = new StringWriter();
                        freemarkerTemplate.process(params, sw);
                        entity.setMessageContent(sw.toString());
                    } catch (Exception e) {
                        LOGGER.error("短信模板解析错误", e);
                    }

                    entity.setSendDate(now);
                    StringBuilder serialNumber = new StringBuilder(batchNumber);
                    for (int k = 0; k < (4 - String.valueOf(i).length()); k++) {
                        serialNumber.append("0");
                    }
                    serialNumber.append(i);
                    entity.setSerialNumber(serialNumber.toString());
                    this.baseMapper.insert(entity);
                    i++;
                }
            }
        } else {
            LOGGER.debug("Messaging must have targets.");
        }
    }

    @Override
    public List<MessageRequestEntity> getPendingMessageRequestEntities4Messaging(int batchSize) {
        LambdaQueryWrapper<MessageRequestEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MessageRequestEntity::getRequestStatus, CommonProcessStatus.PENDING);
        queryWrapper.orderByAsc(MessageRequestEntity::getId);
        if (batchSize > 0) {
            queryWrapper.last(" limit " + batchSize);
        }
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public List<MessageRequestEntity> getFailMessageRequestEntities4MessagingRetry(int batchSize, int maxRetryCount) {
        if (maxRetryCount < 1) {
            return Collections.emptyList();
        } else {
            LambdaQueryWrapper<MessageRequestEntity> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(MessageRequestEntity::getRequestStatus, CommonProcessStatus.FAIL);
            queryWrapper.lt(MessageRequestEntity::getRequestCount, maxRetryCount);
            queryWrapper.orderByAsc(MessageRequestEntity::getId);
            if (batchSize > 0) {
                queryWrapper.last(" limit " + batchSize);
            }
            return this.baseMapper.selectList(queryWrapper);
        }
    }

    @Override
    public MessageRequestEntity getByVendorMessageIdAndPhone(String messageId, String mobilePhone) {
        if (StringUtils.isBlank(messageId)) {
            return null;
        } else {
            LambdaQueryWrapper<MessageRequestEntity> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(MessageRequestEntity::getMessageId, messageId.trim());
            if (StringUtils.isNotBlank(mobilePhone)) {
                queryWrapper.eq(MessageRequestEntity::getMobilePhone, mobilePhone.trim());
            }
            List<MessageRequestEntity> entities = this.baseMapper.selectList(queryWrapper);
            if (entities != null && entities.size() > 0) {
                return entities.get(0);
            } else {
                return null;
            }
        }
    }
}